package com.envoy.testsuite.dummydevice;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.UnknownHostException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONObject;

/**
 * Simulates a real device sending various requests.
 * @author Angus J. Goldsmith
 *
 */
public class DummyDevice {

  /**
   * The device's id.
   */
  private String deviceId;

  /**
   * Initialises fields.
   * @param iDeviceId the device id.
   */
  public DummyDevice(final String iDeviceId) {
    deviceId = iDeviceId;
  }

  /**
   * Sends a deviceID request.
   * @param url the server url.
   */
  public final void deviceIdRequest(final String url) {
    JSONObject json = new JSONObject();
    json.put("type", "deviceID");
    json.put("deviceID", deviceId);
    //JSONObject response = httpPost(url, json);
  }

  /**
   * Sends a name request.
   * @param url the server url.
   * @param name the name to associate.
   */
  public final void nameRequest(final String url, final String name) {
    JSONObject json = new JSONObject();
    json.put("type", "name");
    json.put("deviceID", deviceId);
    json.put("name", name);
    //JSONObject response = httpPost(url, json);
    httpPost(url, json);
  }

  /**
   * Sends a location request.
   * @param url the server url.
   * @param d the latitude.
   * @param e the longitude.
   * @param i the accuracy.
   * @param date the date.
   */
  public final void locationRequest(final String url, final double d,
      final double e, final int i, final String date) {
    JSONObject json = new JSONObject();
    json.put("type", "position");
    json.put("deviceID", deviceId);
    json.put("latitude", d);
    json.put("longitude", e);
    json.put("accuracy", i);
    json.put("date", date);
    //JSONObject response = httpPost(url, json);
    httpPost(url, json);
  }

  /**
   * Sends a new message request.
   * @param url server url.
   * @param destId eventual destination.
   * @param messageContent the content.
   * @param latitude lat.
   * @param longitude long.
   * @param accuracy accuracy of position.
   * @param date date of position.
   */
  public final void newMessageRequest(final String url, final String destId,
      final String messageContent, final double latitude,
      final double longitude, final int accuracy, final String date) {
    JSONObject json = new JSONObject();
    json.put("type", "new");
    json.put("messageData", messageContent);
    json.put("deviceID", deviceId);
    json.put("destID", destId);
    json.put("latitude", latitude);
    json.put("longitude", longitude);
    json.put("accuracy", accuracy);
    json.put("date", date);
    //JSONObject response = httpPost(url, json);
    httpPost(url, json);
  }
  /**
   * Sends an add request.
   * @param url the server url.
   * @param messageId the message Id.
   * @param messageData the data to add.
   */
  public final void addRequest(final String url, final String messageId,
      final String messageData) {
    JSONObject json = new JSONObject();
    json.put("type", "add");
    json.put("deviceID", deviceId);
    json.put("messageID", messageId);
    json.put("messageData", messageData);
    //JSONObject response = httpPost(url, json);
    httpPost(url, json);
  }
  /**
   * Sends a request to the server.
   * @param url the sever.
   * @param json the JSON to send.
   * @return the response JSON.
   */
  public final JSONObject httpPost(final String url,
      final JSONObject json) {
    try {
      final int timeoutMillisecs = 10000;
      HttpParams httpParams = new BasicHttpParams();
      HttpConnectionParams.setConnectionTimeout(httpParams,
          timeoutMillisecs);
      HttpConnectionParams.setSoTimeout(httpParams, timeoutMillisecs);
      HttpClient client = new DefaultHttpClient(httpParams);
      HttpPost request = new HttpPost(url);
      request.setEntity(new ByteArrayEntity(json.toString().getBytes(
          "UTF8")));
      request.setHeader("json", json.toString());
      HttpResponse response = client.execute(request);
      HttpEntity entity = response.getEntity();
      if (entity != null) {
        InputStream instream = entity.getContent();
        String result = convertStreamToString(instream);
        System.out.println(result);
        JSONObject jsonReceive = new JSONObject(result);
        return jsonReceive;
      }
    } catch (UnknownHostException uhe) {
      // Toast.makeText(parent,
      // "Request failed: " + "Couldn't find \"" + url,
      // Toast.LENGTH_LONG).show();
      uhe.printStackTrace();
    } catch (Throwable t) {
      // Toast.makeText(parent, "Request failed: " + t.toString(),
      // Toast.LENGTH_LONG).show();
      // t.printStackTrace();
      t.printStackTrace();
    }
    return null;
  }

  /**
   * Converts a stream to a string.
   * @param is the input stream.
   * @return the string.
   */
  public static String convertStreamToString(final InputStream is) {
    /*
     * To convert the InputStream to String we use the
     * BufferedReader.readLine() method. We iterate until the BufferedReader
     * return null which means there's no more data to read. Each line will
     * appended to a StringBuilder and returned as String.
     */
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
      while ((line = reader.readLine()) != null) {
        sb.append(line + "\n");
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        is.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return sb.toString();
  }
}
